package edu.arizona.mindseye.swing;

import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

import edu.arizona.mindseye.event.Event;
import edu.arizona.mindseye.event.EventManager;
import edu.arizona.mindseye.event.enums.EventType;
import edu.arizona.mindseye.event.enums.Parameter;

public class BehaviorsDialog extends JDialog {

	private JButton _add;
	private JButton _ok;
	private JButton _cancel;
	
	private JButton _right;
	private JButton _left;
	
	private DefaultListModel _leftModel;
	private JList _leftList;
	
	private DefaultListModel _rightModel;
	private JList _rightList;
	
	private List<String> _behaviors;
	
	private boolean _success;
	
	public BehaviorsDialog(List<String> behaviors) { 
		super((JFrame) null, "Add Behaviors", true);
		
		_behaviors = behaviors;
		
		addComponents();
		addListeners();		
	}
	
	private void addComponents() { 
		setLayout(new GridBagLayout());
		
		_leftModel = new DefaultListModel();
		for (String s : _behaviors)
			_leftModel.addElement(s);
		
		_leftList = new JList(_leftModel);
		
		_rightModel = new DefaultListModel();
		_rightList = new JList(_rightModel);
		
		_add = new JButton("Add Behavior");
		_cancel = new JButton("Cancel");
		_ok = new JButton("Ok");
		
		_right = new JButton(">>");
		_left = new JButton("<<");
		
		JPanel panel = new JPanel();
		panel.setLayout(new GridBagLayout());
		panel.add(new JPanel(), GBC.makeGBC(0, 0, GridBagConstraints.BOTH, 0, 1));
		panel.add(_right, GBC.makeGBC(0, 1, GridBagConstraints.BOTH, 0, 0));
		panel.add(_left, GBC.makeGBC(0, 2, GridBagConstraints.BOTH, 0, 0));
		panel.add(new JPanel(), GBC.makeGBC(0, 3, GridBagConstraints.BOTH, 0, 1));
		
		add(new JScrollPane(_leftList), GBC.makeGBC(0, 0, GridBagConstraints.BOTH, 1.0, 1));
		add(panel, GBC.makeGBC(1, 0, GridBagConstraints.BOTH, 0.0, 1));
		add(new JScrollPane(_rightList), GBC.makeGBC(2, 0, GridBagConstraints.BOTH, 1.0, 1));
		
		JPanel p = new JPanel();
		p.setLayout(new FlowLayout());
		p.add(_add);
		p.add(_ok);
		p.add(_cancel);
		add(p, GBC.makeGBC(0, 1, 3, 1, GridBagConstraints.BOTH, 1, 0));
		
		setSize(500, 300);
	}
	
	private void addListeners() {
		_right.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				move(_leftList, _leftModel, _rightModel);
			} 
		});
		
		_left.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				move(_rightList, _rightModel, _leftModel);
			} 
			
		});
		
		_cancel.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				_success = false;
				setVisible(false);
			} 
		});
		
		_ok.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				if (_rightModel.size() == 0) { 
					JOptionPane.showMessageDialog(null, "You must select at least one behavior or hit cancel");
					return;
				}
				
				_success = true;
				setVisible(false);
			} 
		});
		
		_add.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				String behavior = JOptionPane.showInputDialog(null, "What is the name of the behavior you would like to add?", "Add Behavior");
				if (behavior != null && behavior.trim().length() > 0) { 
					_leftModel.addElement(behavior);
					
					Event event = new Event(EventType.ADD_BEHAVIOR);
					event.addParameter(Parameter.name, behavior);
					EventManager.inst().dispatch(event);
				}
			} 
		});
		
		_leftList.addMouseListener(new DoubleClick(_leftList, _leftModel, _rightModel));
		_rightList.addMouseListener(new DoubleClick(_rightList, _rightModel, _leftModel));
	}
	
	/**
	 * Move a behavior from one list to the other.
	 * @param list
	 * @param orig
	 * @param dest
	 */
	public static void move(JList list, DefaultListModel orig, DefaultListModel dest) { 
		if (orig.size() == 0 || list.getSelectedIndices().length == 0)
			return;

		Object[] selected = list.getSelectedValues();
		for (Object o : selected) { 
			dest.addElement(o);
			orig.removeElement(o);
		}
		list.clearSelection();
	}
	
	public boolean okPressed() { 
		return _success;
	}
	
	public List<String> getBehaviors() { 
		List<String> list = new ArrayList<String>();
		for (int i = 0; i < _rightModel.size(); ++i) { 
			list.add((String) _rightModel.get(i));
		}
		return list;
	}
}

class DoubleClick extends MouseAdapter { 
	
	private JList _list;
	private DefaultListModel _orig;
	private DefaultListModel _dest;
	
	public DoubleClick(JList list, DefaultListModel orig, DefaultListModel dest) { 
		_list = list;
		_orig = orig;
		_dest = dest;
	}
	
	public void mouseClicked(MouseEvent e) { 
		if (e.getClickCount() == 2) { 
			BehaviorsDialog.move(_list, _orig, _dest);
		}
	}
}
